package cz.najman.emdroid.connection;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;

import android.net.Uri;
import android.util.Log;
import cz.najman.emdroid.content.ContentProducer;

public class RestConnectionMethod implements ConnectionMethod {
	DefaultHttpClient mClient;
	private static final String TAG = "RestConnectionMethod";
	
	public RestConnectionMethod() {
		this.mClient = new DefaultHttpClient();
		
		mClient.addRequestInterceptor(new HttpRequestInterceptor() {
			
			@Override
			public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
				/* If the request deos not allready contain the Accept-Encoding Header
				 * we add one that supports gzip encoding
				 */
				if (!request.containsHeader("Accept-Encoding")) {
                    request.addHeader("Accept-Encoding", "gzip");
                }
				if (!request.containsHeader(HTTP.CONTENT_TYPE)) {
					request.addHeader(HTTP.CONTENT_TYPE, "application/xml");
                }
				
			}
		});
		
		mClient.addResponseInterceptor(new HttpResponseInterceptor() {

            public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException {
                HttpEntity entity = response.getEntity();
                Header ceheader = entity.getContentEncoding();
                if (ceheader != null) {
                    HeaderElement[] codecs = ceheader.getElements();
                    for (int i = 0; i < codecs.length; i++) {
                        if (codecs[i].getName().equalsIgnoreCase("gzip")) {
                            response.setEntity(new GzipDecompressingEntity(response.getEntity()));
                            return;
                        }
                    }
                }
            }

        });
	}
	
	@Override
	public int create(Uri uri, ResponseHandler responseHandler, ContentProducer contentProducer) throws ClientProtocolException, IOException {
		HttpEntity entity = new EntityTemplate(contentProducer);
		HttpPost request = new HttpPost(uri.toString());		
		request.setEntity(entity);		
		Log.d(TAG, ">>>> Creating");		
		return mClient.execute(request, responseHandler);
	}

	@Override
	public int retrieve(Uri uri, ResponseHandler responseHandler) throws ClientProtocolException, IOException {
		HttpGet request = new HttpGet(uri.toString());
		Log.d(TAG, ">>>> Retrieving");
		return mClient.execute(request, responseHandler);
	}

	@Override
	public int update(Uri uri, ResponseHandler responseHandler,	ContentProducer contentProducer) {
		// TODO Auto-generated method stub
		return RESPONSE_CODE_OK;
	}

	@Override
	public int delete(Uri uri, ResponseHandler responseHandler) {
		// TODO Auto-generated method stub
		return RESPONSE_CODE_OK;
	}
	
	private class GzipDecompressingEntity extends HttpEntityWrapper {

        public GzipDecompressingEntity(final HttpEntity entity) {
            super(entity);
        }

        @Override
        public InputStream getContent()
            throws IOException, IllegalStateException {

            // the wrapped entity's getContent() decides about repeatability
            InputStream wrappedin = wrappedEntity.getContent();

            return new GZIPInputStream(wrappedin);
        }

        @Override
        public long getContentLength() {
            // length of ungzipped content is not known
            return -1;
        }

    }

}
